﻿#pragma once

#include "ais/ais_base.h"
#include "renderer/renderer.h"

#define CAGD_FRIEND_RENDERER                                                                                           \
    friend class CAGD::RendererExt;                                                                                    \
    friend class CAGD::RendererPoint;                                                                                  \
    friend class CAGD::RendererVector;                                                                                 \
    friend class CAGD::RendererNormal;                                                                                 \
    friend class CAGD::RendererCurve;                                                                                  \
    friend class CAGD::RendererMesh;                                                                                   \
    friend class CAGD::RendererFrame;                                                                                  \
    friend class CAGD::ShdPoint;                                                                                       \
    friend class CAGD::ShdPointCloud;                                                                                  \
    friend class CAGD::ShdVector;                                                                                      \
    friend class CAGD::ShdVectorCloud;                                                                                 \
    friend class CAGD::ShdBox;                                                                                         \
    friend class CAGD::ShdCurve;                                                                                       \
    friend class CAGD::ShdMesh;                                                                                        \
    friend class CAGD::ShdSurface;                                                                                     \
    friend class CAGD::ShdPole;                                                                                        \
    friend class CAGD::ShdPointLight;                                                                                  \
    friend class CAGD::ShdDirLight;                                                                                    \
    friend class CAGD::ShdSpotLight;                                                                                   \
    friend class CAGD::ShdFrame;                                                                                       \
    friend bool init_text_textures(MainOpenGLWidget *parent, int height);                                              \
    friend void destroy_text_textures(MainOpenGLWidget *parent);

namespace CAGD
{

/**
 * 中间垃圾处理类（扩展类）.
 */
class RendererExt : public Renderer
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererExt(MainOpenGLWidget *parent);

    /**
     * @brief 析构.
     * @see
     */
    ~RendererExt();
};

/**
 * 点着色.
 */
class RendererPoint : public RendererExt
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererPoint(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 渲染接口.
     * @see
     */
    void Draw(AIS_Base *obj) const override;
};

/**
 * 向量着色.
 */
class RendererVector : public RendererExt
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererVector(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 渲染接口.
     * @see
     */
    void Draw(AIS_Base *obj) const override;
};

/**
 * 向量云着色.
 */
class RendererNormal : public RendererExt
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererNormal(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 渲染接口.
     * @see
     */
    void Draw(AIS_Base *obj) const override;
};

/**
 * 曲线结构.
 */
class RendererCurve : public RendererExt
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererCurve(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 渲染接口.
     * @see
     */
    void Draw(AIS_Base *obj) const override;
};

/**
 * 网格着色.
 */
class RendererMesh : public RendererExt
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererMesh(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 渲染接口.
     * @see
     */
    void Draw(AIS_Base *obj) const override;
};

/**
 * 帧绘制.
 */
class RendererFrame : public RendererExt
{
  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    RendererFrame(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 预渲染接口.
     * @see
     */
    void Prepare(AIS_Base *obj) const;

    /**
     * @brief 后渲染接口.
     * @see
     */
    void Done(AIS_Base *obj) const;
};

//////////////////////////////////////////////////////////////////////////////////////////
///
///

/**
 * 点云着色器.
 */
class ShdPoint : public RendererPoint
{
  public:
    CAGD_CREATE_RENDERER(ShdPoint)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdPoint(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 点云着色器.
 */
class ShdPointCloud : public RendererPoint
{
  public:
    CAGD_CREATE_RENDERER(ShdPointCloud)

    /**
     * @brief 点云构造.
     * @param parent
     * @see
     */
    ShdPointCloud(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 向量着色器.
 */
class ShdVector : public RendererVector
{
  public:
    CAGD_CREATE_RENDERER(ShdVector)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdVector(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 向量云着色器.
 */
class ShdVectorCloud : public RendererNormal
{
  public:
    CAGD_CREATE_RENDERER(ShdVectorCloud)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdVectorCloud(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 包围盒.
 */
class ShdBox : public RendererCurve
{
  public:
    CAGD_CREATE_RENDERER(ShdBox)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdBox(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 曲线结构.
 */
class ShdCurve : public RendererCurve
{
  public:
    CAGD_CREATE_RENDERER(ShdCurve)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdCurve(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 网格着色.
 */
class ShdMesh : public RendererMesh
{
  public:
    CAGD_CREATE_RENDERER(ShdMesh)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdMesh(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 曲面着色.
 */
class ShdSurface : public RendererMesh
{
  public:
    CAGD_CREATE_RENDERER(ShdSurface)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdSurface(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 控制杆渲染.
 */
class ShdPole : public RendererCurve
{
  public:
    CAGD_CREATE_RENDERER(ShdPole)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdPole(MainOpenGLWidget *parent);

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 点光源着色.
 */
class ShdPointLight : public RendererPoint
{
  public:
    CAGD_CREATE_RENDERER(ShdPointLight)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdPointLight(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 方向光源着色.
 */
class ShdDirLight : public RendererPoint
{
  public:
    CAGD_CREATE_RENDERER(ShdDirLight)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdDirLight(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 聚光源着色.
 */
class ShdSpotLight : public RendererPoint
{
  public:
    CAGD_CREATE_RENDERER(ShdSpotLight)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdSpotLight(MainOpenGLWidget *parent);

    /**
     * @brief 刷新 uniform 变量.
     * @param obj
     * @see
     */
    void UpdateUniform(AIS_Base *obj) override;

    /**
     * @brief 刷新顶点数组.
     * @param obj
     * @see
     */
    void UpdateArray(AIS_Base *obj) override;
};

/**
 * 帧绘制.
 */
class ShdFrame : public RendererFrame
{
  public:
    CAGD_CREATE_RENDERER(ShdFrame)

    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    ShdFrame(MainOpenGLWidget *parent);

    /**
     * @brief 析构文字渲染用的数组.
     * @see
     */
    ~ShdFrame();

    /**
     * @brief 渲染接口.
     * @see
     */
    void Draw(AIS_Base *obj) const override;
};

} // namespace CAGD
